#include <jni.h>
#include <string>
#include "libyuv.h"
#include <cstdint>
#include <sys/time.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LOG_TAG "JniLog"
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

void YV12ToI420(jbyte *src_yv12_data, jint width, jint height, jbyte *dst_i420_data) {
    jbyte *src_yplane = src_yv12_data;
    jbyte *src_uplane = src_yv12_data + width * height;
    jbyte *src_vplane = src_uplane + (width * height / 4);
    jbyte *dst_yplane = dst_i420_data;
    jbyte *dst_uplane = dst_i420_data + width * height;
    jbyte *dst_vplane = dst_uplane + (width * height / 4);
    // YV12 is YVU => Use I420(YUV) copy and flip U and V.
    libyuv::I420Copy(
            (const uint8_t *) src_yplane, width,
            (const uint8_t *) src_vplane, width / 2,
            (const uint8_t *) src_uplane, width / 2,
            (uint8_t *) dst_yplane, width,
            (uint8_t *) dst_uplane, width / 2,
            (uint8_t *) dst_vplane, width / 2,
            width, height);
}

void NV21ToI420(jbyte *src_nv21_data, jint width, jint height, jbyte *dst_i420_data) {
    // NV21 = y plane followed by an interleaved V/U plane, i.e. same as NV12
    // but the U and the V are switched. Use the NV12 function and switch the U
    // and V planes.
    jbyte *src_yplane = src_nv21_data;
    jbyte *src_uvplane = src_nv21_data + width * height;
    jbyte *dst_yplane = dst_i420_data;
    jbyte *dst_uplane = dst_i420_data + width * height;
    jbyte *dst_vplane = dst_uplane + (width * height / 4);
    libyuv::NV21ToI420(
            (const uint8_t *) src_yplane, width,
            (const uint8_t *) src_uvplane, width,
            (uint8_t *) dst_yplane, width,
            (uint8_t *) dst_vplane, width / 2,
            (uint8_t *) dst_uplane, width / 2,
            width, height);
}

void I420ToNv12(jbyte *src_i420_data, jint width, jint height, jbyte *src_nv12_data) {
    jint src_y_size = width * height;
    jint src_u_size = (width >> 1) * (height >> 1);

    jbyte *src_nv12_y_data = src_nv12_data;
    jbyte *src_nv12_uv_data = src_nv12_data + src_y_size;

    jbyte *src_i420_y_data = src_i420_data;
    jbyte *src_i420_u_data = src_i420_data + src_y_size;
    jbyte *src_i420_v_data = src_i420_data + src_y_size + src_u_size;


    libyuv::I420ToNV12(
            (const uint8_t *) src_i420_y_data, width,
            (const uint8_t *) src_i420_u_data, width >> 1,
            (const uint8_t *) src_i420_v_data, width >> 1,
            (uint8_t *) src_nv12_y_data, width,
            (uint8_t *) src_nv12_uv_data, width,
            width, height);
}

void I420ToNv21(jbyte *src_i420_data, jint width, jint height, jbyte *src_nv21_data) {
    jint src_y_size = width * height;
    jint src_u_size = (width >> 1) * (height >> 1);

    jbyte *src_nv12_y_data = src_nv21_data;
    jbyte *src_nv12_uv_data = src_nv21_data + src_y_size;

    jbyte *src_i420_y_data = src_i420_data;
    jbyte *src_i420_u_data = src_i420_data + src_y_size;
    jbyte *src_i420_v_data = src_i420_data + src_y_size + src_u_size;


    libyuv::I420ToNV21(
            (const uint8_t *) src_i420_y_data, width,
            (const uint8_t *) src_i420_u_data, width >> 1,
            (const uint8_t *) src_i420_v_data, width >> 1,
            (uint8_t *) src_nv12_y_data, width,
            (uint8_t *) src_nv12_uv_data, width,
            width, height);
}

void NV21ToNV12(jbyte *src_nv21_data, jbyte *dst_nv12_data, jint width, jint height) {
    jint src_y_size = width * height;

    jbyte *src_nv21_y_data = src_nv21_data;
    jbyte *src_nv21_vu_data = src_nv21_data + src_y_size;

    jbyte *dst_nv12_y_data = dst_nv12_data;
    jbyte *dst_nv12_uv_data = dst_nv12_data + src_y_size;

    libyuv::NV21ToNV12(
            (const uint8_t *) src_nv21_y_data,
            width,
            (const uint8_t *) src_nv21_vu_data,
            width,
            (uint8_t *) dst_nv12_y_data,
            width,
            (uint8_t *) dst_nv12_uv_data,
            width,
            width,
            height
            );
}

void NV21ToRGB(jbyte *src_nv21_data, jbyte *dst_grb_data, jint width, jint height) {
    jint src_y_size = width * height;

    jbyte *src_nv21_y_data = src_nv21_data;
    jbyte *src_nv21_vu_data = src_nv21_data + src_y_size;

    libyuv::NV21ToRGB24(
            (const uint8_t *) src_nv21_y_data, width,
            (const uint8_t *) src_nv21_vu_data, width,
            reinterpret_cast<uint8_t*>(dst_grb_data), width * 3,
            width, height
    );
}

void NV21ToNV12Inplace(jbyte *src_nv21_data, jbyte *dst_nv12_data, jint width, jint height) {
    jint src_y_size = width * height;
    jbyte *src_nv21_vu_data = src_nv21_data + src_y_size;
    jbyte *dst_nv12_uv_data = dst_nv12_data;
//NV21ToNV12Inplace(uint8_t *src_vu, int src_stride_vu, uint8_t *tmp_uv, int tmp_stride_uv, int width, int height);
    libyuv::NV21ToNV12Inplace(
            (uint8_t *) src_nv21_vu_data,
            width,
            (uint8_t *) dst_nv12_uv_data,
            width,
            width,
            height
            );
}

void rotateI420(jbyte *src_i420_data, jint width, jint height, jbyte *dst_i420_data, jint degree) {
    jint src_i420_y_size = width * height;
    jint src_i420_u_size = (width >> 1) * (height >> 1);

    jbyte *src_i420_y_data = src_i420_data;
    jbyte *src_i420_u_data = src_i420_data + src_i420_y_size;
    jbyte *src_i420_v_data = src_i420_data + src_i420_y_size + src_i420_u_size;

    jbyte *dst_i420_y_data = dst_i420_data;
    jbyte *dst_i420_u_data = dst_i420_data + src_i420_y_size;
    jbyte *dst_i420_v_data = dst_i420_data + src_i420_y_size + src_i420_u_size;

    //要注意这里的width和height在旋转之后是相反的
    if (degree == libyuv::kRotate90 || degree == libyuv::kRotate270) {
        libyuv::I420Rotate((const uint8_t *) src_i420_y_data, width,
                           (const uint8_t *) src_i420_u_data, width >> 1,
                           (const uint8_t *) src_i420_v_data, width >> 1,
                           (uint8_t *) dst_i420_y_data, height,
                           (uint8_t *) dst_i420_u_data, height >> 1,
                           (uint8_t *) dst_i420_v_data, height >> 1,
                           width, height,
                           (libyuv::RotationMode) degree);
    } else {
        libyuv::I420Rotate((const uint8_t *) src_i420_y_data, width,
                           (const uint8_t *) src_i420_u_data, width >> 1,
                           (const uint8_t *) src_i420_v_data, width >> 1,
                           (uint8_t *) dst_i420_y_data, width,
                           (uint8_t *) dst_i420_u_data, width >> 1,
                           (uint8_t *) dst_i420_v_data, width >> 1,
                           width, height,
                           (libyuv::RotationMode) degree);
    }
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_YV12ToI420(JNIEnv *env, jclass clazz, jbyteArray src, jbyteArray dest,
                                        jint width, jint height) {
    jbyte *srcP = env->GetByteArrayElements(src, NULL);
    jbyte *destP = env->GetByteArrayElements(dest, NULL);
    YV12ToI420(srcP, width, height, destP);
    env->ReleaseByteArrayElements(src, srcP, 0);
    env->ReleaseByteArrayElements(dest, destP, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_NV21ToI420(JNIEnv *env, jclass clazz, jbyteArray nv21_bytes,
                                        jbyteArray i420_bytes, jint width, jint height) {
    jbyte *nv21_bytes_p = env->GetByteArrayElements(nv21_bytes, NULL);
    jbyte *i420_bytes_p = env->GetByteArrayElements(i420_bytes, NULL);
    // nv21转化为i420
    NV21ToI420(nv21_bytes_p, width, height, i420_bytes_p);
    env->ReleaseByteArrayElements(nv21_bytes, nv21_bytes_p, 0);
    env->ReleaseByteArrayElements(i420_bytes, i420_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_I420Rotate(JNIEnv *env, jclass clazz, jbyteArray src_i420_bytes,
                                        jbyteArray dest_i420_bytes, jint width, jint height,
                                        jint degree) {
    jbyte *src_i420_bytes_p = env->GetByteArrayElements(src_i420_bytes, NULL);
    jbyte *dest_i420_bytes_p = env->GetByteArrayElements(dest_i420_bytes, NULL);
    rotateI420(src_i420_bytes_p, width, height, dest_i420_bytes_p, degree);
    env->ReleaseByteArrayElements(src_i420_bytes, src_i420_bytes_p, 0);
    env->ReleaseByteArrayElements(dest_i420_bytes, dest_i420_bytes_p, 0);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_I420ToNV12(JNIEnv *env, jclass clazz, jbyteArray i420_bytes,
                                        jbyteArray nv12_bytes, jint width, jint height) {
    jbyte *i420_bytes_p = env->GetByteArrayElements(i420_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
    I420ToNv12(i420_bytes_p, width, height, nv12_bytes_p);
    env->ReleaseByteArrayElements(i420_bytes, i420_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_YV12ToNV12Rotate180(JNIEnv *env, jclass clazz, jbyteArray yv12_bytes,
                                                 jbyteArray nv12_bytes, jint width, jint height) {
    jbyte *yv12_bytes_p = env->GetByteArrayElements(yv12_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
//    const uint8_t *src_y, int src_stride_y, const uint8_t *src_v,
//    int src_stride_v, const uint8_t *src_u, int src_stride_u,
//    uint8_t *dst_y, int dst_stride_y, uint8_t *dst_uv,
//            int dst_stride_uv, int width, int height

    jint src_yv12_y_size = width * height;
    jint src_yv12_v_size = (width >> 1) * (height >> 1);

    jbyte *src_yv12_y_data = yv12_bytes_p;
    jbyte *src_yv12_v_data = yv12_bytes_p + src_yv12_y_size;
    jbyte *src_yv12_u_data = yv12_bytes_p + src_yv12_y_size + src_yv12_v_size;

    jbyte *dst_nv12_y_data = nv12_bytes_p;
    jbyte *dst_nv12_uv_data = nv12_bytes_p + src_yv12_y_size;


    libyuv::YV12ToNV12Rotate180(reinterpret_cast<const uint8_t *>(src_yv12_y_data), width,
                                reinterpret_cast<const uint8_t *>(src_yv12_v_data), width >> 1,
                                reinterpret_cast<const uint8_t *>(src_yv12_u_data), width >> 1,
                                reinterpret_cast<uint8_t *>(dst_nv12_y_data), width,
                                reinterpret_cast<uint8_t *>(dst_nv12_uv_data), width, width, height);
    env->ReleaseByteArrayElements(yv12_bytes, yv12_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_YV12ToNV12Rotate270Or90(JNIEnv *env, jclass clazz, jbyteArray yv12_bytes,
                                                 jbyteArray nv12_bytes, jint width, jint height, jboolean is270) {
    jbyte *yv12_bytes_p = env->GetByteArrayElements(yv12_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
//    const uint8_t *src_y, int src_stride_y, const uint8_t *src_v,
//    int src_stride_v, const uint8_t *src_u, int src_stride_u,
//    uint8_t *dst_y, int dst_stride_y, uint8_t *dst_uv,
//            int dst_stride_uv, int width, int height

    jint src_yv12_y_size = width * height;
    jint src_yv12_v_size = (width >> 1) * (height >> 1);

    jbyte *src_yv12_y_data = yv12_bytes_p;
    jbyte *src_yv12_v_data = yv12_bytes_p + src_yv12_y_size;
    jbyte *src_yv12_u_data = yv12_bytes_p + src_yv12_y_size + src_yv12_v_size;

    jbyte *dst_nv12_y_data = nv12_bytes_p;
    jbyte *dst_nv12_uv_data = nv12_bytes_p + src_yv12_y_size;


    libyuv::YV12ToNV12Rotate270Or90(reinterpret_cast<const uint8_t *>(src_yv12_y_data), width,
                                reinterpret_cast<const uint8_t *>(src_yv12_v_data), width >> 1,
                                reinterpret_cast<const uint8_t *>(src_yv12_u_data), width >> 1,
                                reinterpret_cast<uint8_t *>(dst_nv12_y_data), height,
                                reinterpret_cast<uint8_t *>(dst_nv12_uv_data), height, width, height, is270);
    env->ReleaseByteArrayElements(yv12_bytes, yv12_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_NV21ToNV12(JNIEnv *env, jclass clazz, jbyteArray nv21_bytes,
                                        jbyteArray nv12_bytes, jint width, jint height) {
    jbyte *nv21_bytes_p = env->GetByteArrayElements(nv21_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
    NV21ToNV12(nv21_bytes_p, nv12_bytes_p, width, height);
    env->ReleaseByteArrayElements(nv21_bytes, nv21_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_NV21ToRGB(JNIEnv *env, jclass clazz, jbyteArray nv21_bytes,
                                       jbyteArray rgb_bytes, jint width, jint height) {
    jbyte *nv21_bytes_p = env->GetByteArrayElements(nv21_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(rgb_bytes, NULL);
    NV21ToRGB(nv21_bytes_p, nv12_bytes_p, width, height);
    env->ReleaseByteArrayElements(nv21_bytes, nv21_bytes_p, 0);
    env->ReleaseByteArrayElements(rgb_bytes, nv12_bytes_p, 0);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_NV21ToNV12Inplace(JNIEnv *env, jclass clazz, jbyteArray nv21_bytes,
                                               jbyteArray nv12_bytes, jint width, jint height) {
    jbyte *nv21_bytes_p = env->GetByteArrayElements(nv21_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
    NV21ToNV12Inplace(nv21_bytes_p, nv12_bytes_p, width, height);
    env->ReleaseByteArrayElements(nv21_bytes, nv21_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_I420ToNV21(JNIEnv *env, jclass clazz, jbyteArray i420_bytes,
                                        jbyteArray nv21_bytes, jint width, jint height) {
    jbyte *i420_bytes_p = env->GetByteArrayElements(i420_bytes, NULL);
    jbyte *nv21_bytes_p = env->GetByteArrayElements(nv21_bytes, NULL);
    I420ToNv21(i420_bytes_p, width, height, nv21_bytes_p);
    env->ReleaseByteArrayElements(i420_bytes, i420_bytes_p, 0);
    env->ReleaseByteArrayElements(nv21_bytes, nv21_bytes_p, 0);
}

static int16_t mixing(int32_t volume, double& f) {
    float v = (float)volume;
    volume *= f;
    if (volume > INT16_MAX) {
        f = INT16_MAX / v;
        volume = INT16_MAX;
    } else if (v < INT16_MIN) {
        f = INT16_MIN / v;
        volume = INT16_MIN;
    }

    if (f < 1) {
        f += ((1 - f) / 16);
    }

    return int16_t(volume);
}

void change_volume(int8_t* volumes, size_t size, double factor, double* f) {
    int32_t volume;
    int16_t* p;
    size_t n;
    if (factor == 1 || factor <= 0 || factor > 5) {
        return;
    }

    p = (int16_t*)volumes;
    n = size / sizeof(int16_t);
    for (size_t i = 0; i < n; i++) {
        volume = *p * factor;
        /*if (-100 < *p && *p <= 100) {
            *p = 0;
        } else*/ {
            *p = mixing(volume, *f);
        }
        p++;
    }
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_audioEnhance(JNIEnv *env, jclass clazz, jbyteArray audio_bytes, jdouble factor, jdoubleArray f) {
    jbyte *audio_bytes_p = env->GetByteArrayElements(audio_bytes, NULL);
    jdouble *f_bytes_p = env->GetDoubleArrayElements(f, NULL);
    jsize length = env->GetArrayLength(audio_bytes);
    change_volume(audio_bytes_p, length, factor, f_bytes_p);
    env->ReleaseByteArrayElements(audio_bytes, audio_bytes_p, 0);
    env->ReleaseDoubleArrayElements(f, f_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_pcmFileToWavFile(JNIEnv *env, jclass clazz, jstring pcm_file_path, jint channel_count, jint simple_rate, jstring wav_file_path) {
    LOGD("Hello World");
}

/** 把一个jstring转换成一个c语言的char* 类型. */
char* _JString2CStr(JNIEnv* env, jstring jstr) {
    jclass clazz = (*env).FindClass("java/lang/String");
    jstring charset = (*env).NewStringUTF("GB2312");
    jmethodID mid = (*env).GetMethodID(clazz, "getBytes", "(Ljava/lang/String;)[B");
    auto jBtyeArr = (jbyteArray)(*env).CallObjectMethod(jstr, mid, charset);
    jsize arrLength = (*env).GetArrayLength(jBtyeArr);
    jbyte* jByteArrPointer = (*env).GetByteArrayElements(jBtyeArr, JNI_FALSE);

    char* cCharPointer = nullptr;
    if(arrLength > 0) {
        cCharPointer = (char*) malloc(arrLength + 1); //"\0"
        memcpy(cCharPointer, jByteArrPointer, arrLength);
        cCharPointer[arrLength] = 0;
    }
    (*env).ReleaseByteArrayElements(jBtyeArr, jByteArrPointer,0);
    return cCharPointer;
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_RGBAToARGB(JNIEnv *env, jclass clazz, jbyteArray rgba_bytes, jint arrayOffset, jbyteArray argb_bytes, jint width, jint height) {
    jbyte *rgba_bytes_p = env->GetByteArrayElements(rgba_bytes, NULL);
    jbyte *argb_bytes_p = env->GetByteArrayElements(argb_bytes, NULL);

//    libyuv::RGBAToARGB(
    libyuv::ARGBToRGBA( // 它的功能其实是RGBAToARGB，而RGBAToARGB的功能是ARGBToRGBA
            (const uint8_t *) (rgba_bytes_p + arrayOffset), // const uint8_t* src_rgba,
            width * 4, // int src_stride_rgba,
            (uint8_t *) argb_bytes_p, // uint8_t* dst_argb,
            width * 4, // int dst_stride_argb,
            width, // int width,
            height// int height
            );

    env->ReleaseByteArrayElements(rgba_bytes, rgba_bytes_p, 0);
    env->ReleaseByteArrayElements(argb_bytes, argb_bytes_p, 0);
}

extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_blendARGBToNV12(JNIEnv *env, jclass clazz, jbyteArray argb_bytes, jbyteArray nv12_bytes, jbyteArray dest_nv12_bytes, jbyteArray argb_for_nv12, jbyteArray argb_dest, jint width, jint height) {
    jbyte *argb_bytes_p = env->GetByteArrayElements(argb_bytes, NULL);
    jbyte *nv12_bytes_p = env->GetByteArrayElements(nv12_bytes, NULL);
    jbyte *dest_nv12_bytes_p = env->GetByteArrayElements(dest_nv12_bytes, NULL);
    jbyte *argb_for_nv12_bytes_p = env->GetByteArrayElements(argb_for_nv12, NULL);
    jbyte *argb_dest_p = env->GetByteArrayElements(argb_dest, NULL);

//    clock_t start = clock();
    // 把NV12的视频图片转换为ARGB格式
    libyuv::NV12ToARGB(
            (uint8_t *) nv12_bytes_p, // const uint8_t* src_y,
            width, // int src_stride_y,
            (uint8_t *) nv12_bytes_p + width * height, // const uint8_t* src_uv,
            width, // int src_stride_uv,
            (uint8_t *) argb_for_nv12_bytes_p, // uint8_t* dst_argb,
            width * 4, // int dst_stride_argb,
            width, // int width,
            height  // int height
            );
//    LOGD("NV12ToARGB useTime = %ld", clock() - start);

//    start = clock();
    // 把ARGB的视频图片和ARGB的水印混合在一起
    libyuv::ARGBBlend(
//    libyuv::ARGBAdd(
            (uint8_t *) argb_bytes_p, // const uint8_t* src_argb0,
            width * 4, // int src_stride_argb0,
            (uint8_t *) argb_for_nv12_bytes_p, // const uint8_t* src_argb1,
            width * 4, // int src_stride_argb1,
            (uint8_t *) argb_dest_p, // uint8_t* dst_argb,
            width * 4, // int dst_stride_argb,
            width, // int width,
            height // int height
    );
//    LOGD("ARGBBlend useTime = %ld", clock() - start);

//    start = clock();
    // 把混合成的ARGB图片转换为NV12格式
    libyuv::ARGBToNV12(
            (uint8_t *) argb_dest_p, // const uint8_t* src_argb,
            width * 4, // int src_stride_argb,
            (uint8_t *) dest_nv12_bytes_p, // uint8_t* dst_y,
            width, // int dst_stride_y,
            (uint8_t *) dest_nv12_bytes_p + width * height, // uint8_t* dst_uv,
            width, // int dst_stride_uv,
            width, // int width,
            height // int height
            );
//    LOGD("ARGBToNV12 useTime = %ld", clock() - start);

    env->ReleaseByteArrayElements(argb_bytes, argb_bytes_p, 0);
    env->ReleaseByteArrayElements(nv12_bytes, nv12_bytes_p, 0);
    env->ReleaseByteArrayElements(dest_nv12_bytes, dest_nv12_bytes_p, 0);
    env->ReleaseByteArrayElements(argb_for_nv12, argb_for_nv12_bytes_p, 0);
    env->ReleaseByteArrayElements(argb_dest, argb_dest_p, 0);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_doubango_jni_Libyuv_fillBytesToMat(JNIEnv *env, jclass clazz, jbyteArray bytes,
                                            jobject matAddr) {
//    cv::Mat* mat = (cv::Mat*) matAddr;
//    jbyte* javaBytes = env->GetByteArrayElements(bytes, nullptr);
//    if (javaBytes && mat->isContinuous()) {
//        memcpy(mat->data, javaBytes, mat->total() * mat->elemSize());
//    }
//    env->ReleaseByteArrayElements(bytes, javaBytes, JNI_ABORT);
}